added a twitter user agent to fetch tweets from a specificied user

Albert Sun 12 years ago
parent
commit
d001d10334
1 changed files with 177 additions and 0 deletions
  1. 177 0
      app/models/agents/twitter_user_agent.rb

+ 177 - 0
app/models/agents/twitter_user_agent.rb

@@ -0,0 +1,177 @@
1
+require "twitter"
2
+
3
+module Agents
4
+  class TwitterUserAgent < Agent
5
+    cannot_receive_events!
6
+
7
+    description <<-MD
8
+      The TwitterUserAgent follows the timeline of a specified Twitter user.
9
+
10
+      You must set up a Twitter app and provide it's `consumer_key`, `consumer_secret`, `oauth_token` and `oauth_token_secret`, (Also shown as "Access token" on the Twitter developer's site.) along with the `username` of the Twitter user to monitor.
11
+
12
+      Set `expected_update_period_in_days` to the maximum amount of time that you'd expect to pass between Events being created by this Agent.
13
+    MD
14
+
15
+    event_description <<-MD
16
+      Events are the raw JSON provided by the Twitter API. Should look something like:
17
+
18
+        {
19
+         :created_at=>"Thu Apr 04 13:27:48 +0000 2013",
20
+         :id=>319803490421596160,
21
+         :id_str=>"319803490421596160",
22
+         :text=>
23
+          "In which @jeresig goes to an art gallery and is \"the JavaScript programmer\". http://t.co/gt3PT1d3G1",
24
+         :source=>
25
+          "<a href=\"http://itunes.apple.com/us/app/twitter/id409789998?mt=12\" rel=\"nofollow\">Twitter for Mac</a>",
26
+         :truncated=>false,
27
+         :in_reply_to_status_id=>nil,
28
+         :in_reply_to_status_id_str=>nil,
29
+         :in_reply_to_user_id=>nil,
30
+         :in_reply_to_user_id_str=>nil,
31
+         :in_reply_to_screen_name=>nil,
32
+         :user=>
33
+          {:id=>2341001,
34
+           :id_str=>"2341001",
35
+           :name=>"Albert Sun",
36
+           :screen_name=>"albertsun",
37
+           :location=>"New York, NY",
38
+           :description=>
39
+            "News apps developer at NYT, formerly WSJ. graduated Penn 2010, geek, journalist, data-viz, nlp, gis, digital economics =)",
40
+           :url=>"http://albertsun.info",
41
+           :entities=>
42
+            {:url=>
43
+              {:urls=>
44
+                [{:url=>"http://albertsun.info",
45
+                  :expanded_url=>nil,
46
+                  :indices=>[0, 21]}]},
47
+             :description=>{:urls=>[]}},
48
+           :protected=>false,
49
+           :followers_count=>1857,
50
+           :friends_count=>798,
51
+           :listed_count=>115,
52
+           :created_at=>"Mon Mar 26 19:22:05 +0000 2007",
53
+           :favourites_count=>9,
54
+           :utc_offset=>-18000,
55
+           :time_zone=>"Eastern Time (US & Canada)",
56
+           :geo_enabled=>false,
57
+           :verified=>false,
58
+           :statuses_count=>2572,
59
+           :lang=>"en",
60
+           :contributors_enabled=>false,
61
+           :is_translator=>false,
62
+           :profile_background_color=>"1B2A2B",
63
+           :profile_background_image_url=>
64
+            "http://a0.twimg.com/profile_background_images/2802438/twitterbg.jpg",
65
+           :profile_background_image_url_https=>
66
+            "https://si0.twimg.com/profile_background_images/2802438/twitterbg.jpg",
67
+           :profile_background_tile=>false,
68
+           :profile_image_url=>
69
+            "http://a0.twimg.com/profile_images/110500205/profile-square_normal.jpg",
70
+           :profile_image_url_https=>
71
+            "https://si0.twimg.com/profile_images/110500205/profile-square_normal.jpg",
72
+           :profile_link_color=>"0000FF",
73
+           :profile_sidebar_border_color=>"87BC44",
74
+           :profile_sidebar_fill_color=>"E0FF92",
75
+           :profile_text_color=>"000000",
76
+           :profile_use_background_image=>true,
77
+           :default_profile=>false,
78
+           :default_profile_image=>false,
79
+           :following=>false,
80
+           :follow_request_sent=>false,
81
+           :notifications=>false},
82
+         :geo=>nil,
83
+         :coordinates=>nil,
84
+         :place=>nil,
85
+         :contributors=>nil,
86
+         :retweet_count=>0,
87
+         :favorite_count=>0,
88
+         :entities=>
89
+          {:hashtags=>[],
90
+           :urls=>
91
+            [{:url=>"http://t.co/gt3PT1d3G1",
92
+              :expanded_url=>
93
+               "http://www.nytimes.com/2013/04/04/fashion/art-and-techology-a-clash-of-cultures.html?pagewanted=all",
94
+              :display_url=>"nytimes.com/2013/04/04/fas",
95
+              :indices=>[77, 99]}],
96
+           :user_mentions=>
97
+            [{:screen_name=>"jeresig",
98
+              :name=>"John Resig",
99
+              :id=>752673,
100
+              :id_str=>"752673",
101
+              :indices=>[9, 17]}]},
102
+         :favorited=>false,
103
+         :retweeted=>false,
104
+         :possibly_sensitive=>false,
105
+         :lang=>"en"
106
+        }
107
+    MD
108
+
109
+    default_schedule "every_1h"
110
+
111
+    def validate_options
112
+      unless options[:username].present? && options[:expected_update_period_in_days].present? && options[:consumer_key].present? && options[:consumer_secret].present? && options[:oauth_token].present? && options[:oauth_token_secret].present?
113
+        errors.add(:base, "expected_update_period_in_days, username, consumer_key, consumer_secret, oauth_token and oauth_token_secret are required")
114
+      end
115
+    end
116
+
117
+    def working?
118
+      (event = event_created_within(options[:expected_update_period_in_days].to_i.days)) && event.payload.present?
119
+    end
120
+
121
+    def default_options
122
+      {
123
+          :username => "tectonic",
124
+          :expected_update_period_in_days => "2",
125
+          :consumer_key => "---",
126
+          :consumer_secret => "---",
127
+          :oauth_token => "---",
128
+          :oauth_token_secret => "---"
129
+      }
130
+    end
131
+
132
+    # def process_tweet(filter, status)
133
+    #   if options[:generate] == "counts"
134
+    #     # Avoid memory pollution
135
+    #     me = Agent.find(id)
136
+    #     me.memory[:filter_counts] ||= {}
137
+    #     me.memory[:filter_counts][filter.to_sym] ||= 0
138
+    #     me.memory[:filter_counts][filter.to_sym] += 1
139
+    #     me.save!
140
+    #   else
141
+    #     create_event :payload => status.merge(:filter => filter.to_s)
142
+    #   end
143
+    # end
144
+
145
+    def check
146
+      Twitter.configure do |config|
147
+        config.consumer_key = options[:consumer_key]
148
+        config.consumer_secret = options[:consumer_secret]
149
+        config.oauth_token = options[:oauth_token]
150
+        config.oauth_token_secret = options[:oauth_token_secret]
151
+      end
152
+
153
+      since_id = memory[:since_id] || nil
154
+      max_id = memory[:max_id] || nil
155
+      opts = {:count => 200, :include_rts => true, :exclude_replies => false, :include_entities => true, :contributor_details => true}
156
+      opts.merge! :since_id => since_id unless since_id.nil?
157
+      opts.merge! :max_id => max_id unless max_id.nil?
158
+
159
+      tweets = Twitter.user_timeline(options[:username], opts)
160
+
161
+      tweets.each do |tweet|
162
+        memory[:since_id] = tweet.id if !memory[:since_id] || (tweet.id > memory[:since_id])
163
+
164
+        create_event :payload => tweet.attrs
165
+      end
166
+
167
+      save!
168
+      # if memory[:filter_counts] && memory[:filter_counts].length > 0
169
+      #   memory[:filter_counts].each do |filter, count|
170
+      #     create_event :payload => { :filter => filter.to_s, :count => count, :time => Time.now.to_i }
171
+      #   end
172
+      #   memory[:filter_counts] = {}
173
+      #   save!
174
+      # end
175
+    end
176
+  end
177
+end